package common05.utils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;

public class LocalDateTimeUtils {

    /**
     * 一天的小时数
     */
    public static final long ONE_DAY_HOUR_NUM = 24L;

    /**
     * 一天的分钟数
     */
    public static final long ONE_DAY_MIN_NUM = 60L * ONE_DAY_HOUR_NUM;

    /**
     * 一天的秒数
     */
    public static final long ONE_DAY_SECOND_NUM = 60L * ONE_DAY_MIN_NUM;

    /**
     * 一天的毫秒数
     */
    public static final long ONE_DAY_MS_NUM = 1000L * ONE_DAY_SECOND_NUM;


    /**
     * 各种日期格式
     */
    public static final String TIME_PATTERN_COMMON = "yyyy-MM-dd HH:mm:ss";
    public static final String TIME_PATTERN_YEAR_MONTH_DAY_HOUR_MIN = "yyyy-MM-dd HH:mm";
    public static final String TIME_PATTERN_YEAR_MONTH_DAY_HOUR = "yyyy-MM-dd HH";
    public static final String TIME_PATTERN_YEAR_MONTH_DAY = "yyyy-MM-dd";
    public static final String TIME_PATTERN_YEAR_MONTH = "yyyy-MM";
    public static final String TIME_PATTERN_YEAR = "yyyy";


    /**
     * 进阶方法
     */
    /*===============================================================================================================*/
    public static long getDayStartByLong(long timestamp) {
        return localDateToLong(longToLocalDate(timestamp));
    }

    public static long getDayStartByDate(Date date) {
        return localDateToLong(dateToLocalDate(date));
    }

    public static long getDayStartByLocalDateTime(LocalDateTime localDateTime) {
        return localDateToLong(localDateTimeToLocalDate(localDateTime));
    }

    public static long getDayStartByLocalDate(LocalDate localDate) {
        return localDateToLong(localDate);
    }

    public static long getDayStartByString(String time) throws ParseException {
        return getDayStartByString(time, TIME_PATTERN_COMMON);
    }

    public static long getDayStartByString(String time, String pattern) throws ParseException {
        return localDateToLong(stringToLocalDate(time, pattern));
    }


    /**
     * 转字符串的方法
     */
    /*===============================================================================================================*/
    public static String dateToString(Date date) {
        return dateToString(date, TIME_PATTERN_COMMON);
    }

    public static String dateToString(Date date, String pattern) {
        return patternToSimpleDateFormat(pattern).format(date);
    }


    public static String localDateTimeToString(LocalDateTime localDateTime) {
        return localDateTimeToString(localDateTime, TIME_PATTERN_COMMON);
    }

    public static String localDateTimeToString(LocalDateTime localDateTime, String pattern) {
        return DateTimeFormatter.ofPattern(pattern).format(localDateTime);
    }


    public static String localDateToString(LocalDate localDate) {
        return localDateToString(localDate, TIME_PATTERN_COMMON);
    }

    public static String localDateToString(LocalDate localDate, String pattern) {
        return localDateTimeToString(localDateToLocalDateTime(localDate), pattern);
    }

    public static String longToString(long timestamp) {
        return longToString(timestamp, TIME_PATTERN_COMMON);
    }

    public static String longToString(long timestamp, String pattern) {
        return localDateTimeToString(longToLocalDateTime(timestamp), pattern);
    }


    /**
     * 转LocalDateTime的方法
     */
    /*===============================================================================================================*/
    public static LocalDateTime stringToLocalDateTime(String time) throws ParseException {
        return stringToLocalDateTime(time, TIME_PATTERN_COMMON);
    }

    public static LocalDateTime stringToLocalDateTime(String time, String pattern) throws ParseException {
        return dateToLocalDateTime(stringToDate(time, pattern));
    }

    public static LocalDateTime dateToLocalDateTime(Date date) {
        return LocalDateTime.ofInstant(dateToInstant(date), ZoneId.systemDefault());
    }

    public static LocalDateTime longToLocalDateTime(long timestamp) {
        return LocalDateTime.ofInstant(longToInstant(timestamp), ZoneId.systemDefault());
    }

    public static LocalDateTime localDateToLocalDateTime(LocalDate localDate) {
        return localDate.atStartOfDay();
    }

    /**
     * 转LocalDate的方法
     */
    /*===============================================================================================================*/
    public static LocalDate stringToLocalDate(String time) throws ParseException {
        return stringToLocalDate(time, TIME_PATTERN_COMMON);
    }

    public static LocalDate stringToLocalDate(String time, String pattern) throws ParseException {
        return dateToLocalDate(stringToDate(time, pattern));
    }

    public static LocalDate localDateTimeToLocalDate(LocalDateTime localDateTime) {
        return localDateTime.toLocalDate();
    }

    public static LocalDate longToLocalDate(long timestamp) {
        return LocalDate.ofInstant(longToInstant(timestamp), ZoneId.systemDefault());
    }

    public static LocalDate dateToLocalDate(Date date) {
        return LocalDate.ofInstant(dateToInstant(date), ZoneId.systemDefault());
    }

    /**
     * 转Date的方法
     */
    /*===============================================================================================================*/
    public static Date stringToDate(String time) throws ParseException {
        return stringToDate(time, TIME_PATTERN_COMMON);
    }

    public static Date stringToDate(String time, String pattern) throws ParseException {
        return patternToSimpleDateFormat(pattern).parse(time);
    }

    public static Date longToDate(long timestamp) {
        return instantToDate(longToInstant(timestamp));
    }

    public static Date localDateTimeToDate(LocalDateTime localDateTime) {
        return Date.from(localDateTimeToInstant(localDateTime));
    }

    public static Date localDateToDate(LocalDate localDate) {
        return instantToDate(localDateToInstant(localDate));
    }


    /**
     * 转时间戳的方法
     */
    /*===============================================================================================================*/
    public static long stringToLong(String time) throws ParseException {
        return stringToLong(time, TIME_PATTERN_COMMON);
    }

    public static long stringToLong(String time, String pattern) throws ParseException {
        return localDateTimeToLong(stringToLocalDateTime(time, pattern));
    }

    public static long localDateTimeToLong(LocalDateTime localDateTime) {
        return instantToLong(localDateTimeToInstant(localDateTime));
    }

    public static long localDateToLong(LocalDate localDate) {
        return instantToLong(localDateToInstant(localDate));
    }

    public static long dateToLong(Date date) {
        return instantToLong(dateToInstant(date));
    }

    /**
     * 基础方法
     */
    /*===============================================================================================================*/
    private static SimpleDateFormat patternToSimpleDateFormat(String pattern) {
        return new SimpleDateFormat(pattern);
    }

    private static Date instantToDate(Instant instant) {
        return Date.from(instant);
    }

    private static Instant dateToInstant(Date date) {
        return date.toInstant();
    }

    private static Long instantToLong(Instant instant) {
        return instant.toEpochMilli();
    }

    private static Instant longToInstant(Long timestamp) {
        return Instant.ofEpochMilli(timestamp);
    }

    private static Instant localDateTimeToInstant(LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant();
    }

    private static Instant localDateToInstant(LocalDate localDate) {
        return localDateTimeToInstant(localDateToLocalDateTime(localDate));
    }


}
